﻿#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <vector>
#include <list>
#include <map>
#include <array>
#include <string>
#include <algorithm>
#include <stack>

using namespace std;

// C++11测试

#pragma once

#include <iostream>
#include <string>
#include <assert.h>

using namespace std;

namespace my_string
{
    class string
    {
        friend ostream& operator<<(ostream& _cout, const my_string::string& s)
        {
            for (char c : s)
            {
                cout << c;
            }
            cout << endl;

            return _cout;
        }

        friend istream& operator>>(istream& _cin, my_string::string& s)
        {
            // 在每次输入前需要对缓冲区作出处理
            s.clear();

            // 删除存在于最前方的空格与换行符
            char ch = _cin.get();
            while (ch == ' ' || ch == '\n')
            {
                ch = _cin.get();
            }

            // 在这里，我们创建一个临时的缓冲器来存放s
            // 这样的话每次插入字符数只有超过了128时，将其尾插到s中
            // 之后归零i，从而避免扩容,以此提高插入效率
            char buff[128] = { 0 };
            int i = 0;
            while (ch != ' ' && ch != '\n')
            {
                buff[i++] = ch;

                // 当i到达127时将此位置置为'\0'，然后将i重置为0
                if (i == 127)
                {
                    buff[i] = '\0';
                    s += buff;
                    i = 0;
                }

                ch = _cin.get();
            }

            if (i != 0)
            {
                buff[i] = '\0';
                s += buff;
            }

            return _cin;
        }

    public:
        typedef char* iterator;
        typedef const char* const_iterator;


    public:
        // 构造函数
        string(const char* str = "")
        {
            cout << "string(const char* str)" << endl;
            _size = strlen(str);
            _capacity = _size;
            _str = new char[_capacity + 1];// 字符串后有'\0'因此要+1
            memcpy(_str, str, sizeof(char) * (_size + 1));// 与上述同理
        }

        // 拷贝构造函数
        string(const string& s)
        {
            cout << "string(const string& s) -- 拷贝构造" << endl;
            _size = s._size;
            _capacity = s._capacity;
            // 这里不能直接让_str=s._str（即浅拷贝），
            // 不然会导致两个string最后析构时对它们指向的空间析构两次
            // 此外，如果其中一个对象对这片空间的元素进行修改，会对另一个对象造成影响
            // 因此，此处只能使用深拷贝

            _str = new char[s._capacity + 1];
            memcpy(_str, s._str, sizeof(char) * (s._size + 1));
        }

        // 赋值运算符重载
        //string& operator=(const string& s)
        //{
        //    //cout << "string& operator=(string s) -- 深拷贝" << endl;
        //    if (this != &s)
        //    {
        //        string tmp(s);
        //        swap(tmp);
        //    }

        //    return *this;
        //}

        // 赋值运算符重载
        string& operator=(const string& s)
        {
            cout << "string& operator=(string s) -- 深拷贝" << endl;
            if (this != &s)// 与拷贝构造逻辑相同
            {
                _size = s._size;
                _capacity = s._capacity;
                _str = new char[s._capacity + 1];
                memcpy(_str, s._str, sizeof(char) * (s._size + 1));
            }

            return *this;
        }

        // 析构函数
        ~string()
        {
            _size = _capacity = 0;
            delete[] _str;
            _str = nullptr;
        }

        // 迭代器
        const_iterator begin() const
        {
            return _str;
        }

        const_iterator end() const
        {
            return _str + _size;
        }

        iterator begin()
        {
            return _str;
        }

        iterator end()
        {
            return _str + _size;
        }

        // 修改
        void push_back(char c)
        {
            // 当size与capacity相等时需要扩容
            if (_size == _capacity)
            {
                // 扩容逻辑与reserve类似
                char* tmp = new char[_capacity * 2];
                memcpy(tmp, _str, sizeof(char) * _size);
                delete[] _str;
                _str = tmp;

                _capacity *= 2;
            }


            _str[_size++] = c;
        }

        string& operator+=(char c)
        {
            push_back(c);

            return *this;
        }

        string& operator+=(const char* str)
        {
            append(str);

            return *this;
        }

        void append(const char* str)
        {
            // 与push_back的插入逻辑类似
            // 但是扩容大小需要作出变化
            size_t len = strlen(str);
            if (len + _size >= _capacity)
            {
                reserve(2 * (len + _capacity));
            }

            for (size_t i = 0; i < len; i++)
            {
                push_back(str[i]);
            }
        }

        void clear()
        {
            // 容量一般不缩小，以防重复开辟空间降低效率
            _str[0] = '\0';
            _size = 0;
        }

        void swap(string& s)
        {
            std::swap(_str, s._str);
            std::swap(_size, s._size);
            std::swap(_capacity, s._capacity);
        }

        const char* c_str()const
        {
            return _str;
        }

        // 容量
        size_t size()const
        {
            return _size;
        }

        size_t capacity()const
        {
            return _capacity;
        }

        bool empty()const
        {
            return _size == 0;
        }

        void resize(size_t n, char c = '\0')
        {
            if (n < _size)
            {
                _str[_size] = '\0';// 直接将截止位置提前到size的位置即可
            }
            else
            {
                // 如果是情况三先进行扩容，然后统一插入数据
                if (n > _capacity)
                {
                    reserve(n);
                }

                for (int i = _size; i < n; i++)
                {
                    _str[i] = c;
                }
            }

            _size = n;
        }

        void reserve(size_t n)
        {
            if (n > _capacity)
            {
                // 扩容可能会开辟新空间
                char* tmp = new char[n + 1];
                memcpy(tmp, _str, sizeof(char) * (_size + 1));

                delete[] _str;
                _str = tmp;
                _capacity = n;
            }
        }

        // 下标
        char& operator[](size_t index)
        {
            assert(index < _size);

            return *(_str + index);
        }

        const char& operator[](size_t index)const
        {
            assert(index < _size);

            return *(_str + index);
        }

        // 逻辑运算符
        bool operator<(const string& s)
        {
            int i = 0;
            // 一直迭代到两字符不相等或下标i越界
            while (i < _size && i < s.size() && s[i] == _str[i])
            {
                i++;
            }

            // 如果下标i超过了string1的size，需要进行特殊判断
            if (i >= _size)
            {
                //如果两个字符串的大小相等说明此时它们均相同
                if (_size == s.size())
                {
                    return false;
                }
                else//反之表示string1截止在i这个下标处，string1<string2
                {
                    return true;
                }
            }

            // 如果下标i超过了string2的size，此时string1始终是>或=string2的
            // 因此返回false
            if (i >= s.size())
            {
                return false;
            }

            if (_str[i] < s[i])
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        bool operator<=(const string& s)
        {
            return (*this < s || *this == s);
        }

        bool operator>(const string& s)
        {
            return !(*this <= s);
        }

        bool operator>=(const string& s)
        {
            return (*this > s || *this == s);
        }

        bool operator==(const string& s)
        {
            int i = 0;
            while (i < _size && i < s.size() && s[i] == _str[i])
            {
                i++;
            }

            // 此时，下标i要么越界，要么就在两个字符串中分别指向不同的字符
            // 因此，只有当i越界，且两个字符串大小相等时，才能相等，其余情况都不行
            if ((i >= _size || i >= s.size()) && _size == s.size())
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        bool operator!=(const string& s)
        {
            return !(*this == s);
        }

        // 返回c在string中第一次出现的位置
        size_t find(char c, size_t pos = 0) const
        {
            assert(pos < _size);

            int i = 0;
            while (i < _size && _str[i] != c)
            {
                i++;
            }

            if (_str[i] == c)
            {
                return i;
            }
            else
            {
                return npos;
            }
        }

        // 返回子串s在string中第一次出现的位置
        size_t find(const char* s, size_t pos = 0) const
        {
            assert(pos < _size);

            const char* tmp = strstr(_str + pos, s);
            if (tmp != nullptr)
            {
                return tmp - s;
            }
            else
            {
                return npos;
            }
        }

        // 在pos位置上插入字符c/字符串str，并返回该字符的位置
        string& insert(size_t pos, char c)
        {
            assert(pos <= _size);

            // 检查是否需要扩容
            if (_size == _capacity)
            {
                reserve(2 * _capacity);
            }

            // 从最后一个数据开始将每个数据向后挪动
            int i = 0;
            for (i = _size; i > pos; i--)
            {
                _str[i] = _str[i - 1];
            }
            _str[i] = c;
            _size++;

            return *this;
        }

        string& insert(size_t pos, const char* str)
        {
            assert(pos <= _size);

            int len = strlen(str);
            if (_size + len >= _capacity)
            {
                reserve(2 * (_size + len));
            }

            // 向后挪位置腾出空间
            int i = 0;
            // 在这里i与pos比较时会发生隐式类型转换，因此还需要添加一个条件
            for (i = _size - 1; i != -1 && i >= pos; i--)
            {
                _str[i + len] = _str[i];
            }

            // 从pos位置开始将str的内容拷贝到string中
            memcpy(_str + pos, str, sizeof(char) * len);
            _size += len;

            return *this;
        }

        // 删除pos位置上的元素，并返回字符
        string& erase(size_t pos, size_t len)
        {
            assert(pos < _size);

            // 如果pos+len超过了_size，则表示要将pos及其之后的字符全部删除
            if (pos + len >= _size)
            {
                _str[pos] = '\0';
                _size = pos;
            }
            else
            {
                int i = 0;
                for (i = pos + len; i < _size; i++)
                {
                    _str[i - len] = _str[i];
                }

                _size -= len;
            }

            return *this;
        }

        string func();

        // 移动构造
        string(string&& s)
            :_str(nullptr)
            ,_size(0)
            ,_capacity(0)
        {
            cout << "string(string&& s) -- 移动构造" << endl;
            swap(s);
        }

        // 移动赋值
        string& operator=(string&& s)
        {
            cout << "string& operator=(string&& s) -- 移动赋值" << endl;
            swap(s);
            return *this;
        }

    private:
        char* _str;
        size_t _capacity;
        size_t _size;

    public:
        const static size_t npos;
    };

    const size_t npos = -1;
};

//struct Point
//{
//	int _x;
//	int _y;
//};
//
//int main()
//{
//	int array1[] = { 1, 2, 3, 4, 5 };
//	int array2[5] = { 0 };
//	Point p = { 1, 2 };
//
//	return 0;
//}
//struct Point
//{
//	//explicit Point(int x, int y)
//	Point(int x, int y)
//		:_x(x)
//		, _y(y)
//	{
//		cout << "Point(int x, int y)" << endl;
//	}
//
//	int _x;
//	int _y;
//};
//
//// 一切皆可用{}初始化，并且可以不写=
//// 建议日常定义，不要去掉=，但是我们要能看懂
//int main()
//{
//	int x = 1;
//	int y = { 2 };
//	int z{ 3 };
//
//	int a1[] = { 1,2,3 };
//	int a2[] { 1,2,3 };
//
//	// 本质都是调用构造函数
//	Point p0(0, 0);
//	Point p1 = { 1,1 };  // 多参数构造函数隐式类型转换
//	Point p2{ 2,2 };
//
//	const Point& r = { 3,3 };
//
//	int* ptr1 = new int[3]{ 1,2,3 };
//	Point* ptr2 = new Point[2]{p0,p1};
//	Point* ptr3 = new Point[2]{ {0,0},{1,1} };
//
//	return 0;
//}

//int main()
//{
//	// the type of il is an initializer_list 
//	auto il = { 10, 20, 30 };
//	cout << typeid(il).name() << endl;
//	return 0;
//}

//int main()
//{
//	vector<int> v = { 1,2,3,4 };
//	list<int> lt = { 1,2 };
//
//	// 这里{"sort", "排序"}会先初始化构造一个pair对象
//	map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
//
//	// 使用大括号对容器赋值
//	v = { 10, 20, 30 };
//
//	return 0;
//}

//int main()
//{
//	int i = 10;
//
//	auto p = &i;
//	auto pf = strcpy;
//	cout << typeid(p).name() << endl;
//	cout << typeid(pf).name() << endl;
//
//	map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
//	//map<string, string>::iterator it = dict.begin();
//	auto it = dict.begin();
//	return 0;
//}

//class A
//{
//private:
//	decltype(malloc) pf2;
//};
//
//template<class Func>
//class B
//{
//private:
//	Func _f;
//};
//
//int main()
//{
//	auto pf = malloc;
//	auto pf1 = pf;
//
//	// decltype推出对象的类型，再定义变量，或者作为模板实参
//	// 单纯先定义一个变量出现
//	decltype(pf) pf2;
//
//	B<decltype(pf)> bb1;
//
//	const int x = 1;
//	double y = 2.2;
//
//	B<decltype(x * y)> bb2;
//
//	return 0;
//}

//#ifndef NULL
//#ifdef __cplusplus
//#define NULL   0
//#else
//#define NULL   ((void *)0)
//#endif
//#endif

//int main()
//{
//	int array[] = { 1, 2, 3, 4, 5 };
//	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
//	{
//		array[i] *= 2;
//	}
//
//	for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); ++p)
//	{
//		cout << *p << endl;
//	}
//
//	return 0;
//}

//int main()
//{
//	int array[] = { 1, 2, 3, 4, 5 };
//	for (auto& e : array)
//	{
//		e *= 2;
//	}
//	for (auto e : array)
//	{
//		cout << e << " ";
//	}
//
//	return 0;
//}

//int main()
//{
//	// 以下的p、b、c、*p都是左值
//	int* p = new int(0);
//	int b = 1;
//	const int c = 2;
//
//	// 以下几个是对上面左值的左值引用
//	int*& rp = p;
//	int& rb = b;
//	const int& rc = c;
//	int& pvalue = *p;
//
//	return 0;
//}

//int main()
//{
//	double x = 1.1, y = 2.2;
//	// 以下几个都是常见的右值
//	10;
//	x + y;
//	fmin(x, y);
//
//	// 以下几个都是对右值的右值引用
//	int&& rr1 = 10;
//	double&& rr2 = x + y;
//	double&& rr3 = fmin(x, y);
//
//	// 编译报错: error C2106: “=”: 左操作数必须为左值
//	10 = 1;
//	x + y = 1;
//	fmin(x, y) = 1;
//
//	return 0;
//}

//int main()
//{
//	// 左值引用只能引用左值，不能引用右值。
//	int a = 10;
//	int& ra1 = a; // ra为a的别名
//	//int& ra2 = 10;   // 编译失败，因为10是右值
//	
//	// const左值引用既可引用左值，也可引用右值。
//	const int& ra3 = 10;
//	const int& ra4 = a;
//
//	return 0;
//}

//int main()
//{
//	// 右值引用只能右值，不能引用左值。
//	int&& r1 = 10;
//
//	// error C2440: “初始化”: 无法从“int”转换为“int &&”
//	// message : 无法将左值绑定到右值引用
//	int a = 10;
//	int&& r2 = a;
//
//	// 右值引用可以引用move以后的左值
//	int&& r3 = std::move(a);
//
//	return 0;
//}

//void func1(my_string::string s)
//{}
//
//void func2(const my_string::string& s)
//{}
//
//int main()
//{
//	my_string::string s1("hello world");
//
//	// func1和func2的调用我们可以看到
//	// 左值引用做参数减少了拷贝，提高效率的使用场景和价值
//	func1(s1);
//	func2(s1);
//
//	// string operator+=(char ch) 传值返回存在深拷贝
//	// string& operator+=(char ch) 传左值引用没有使用深拷贝，从而提高了效率
//	s1 += '!';
//
//	return 0;
//}

//my_string::string func()
//{
//    my_string::string str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
//    //... 
//
//    return str;
//}
//
//int main()
//{
//    my_string::string ret1;
//    ret1 = func();
//
//	return 0;
//}
//
//int main()
//{
//    my_string::string s1("hello world");
//    // 这里s1是左值，调用的是拷贝构造
//
//    my_string::string s2(s1);
//    my_string::string s3(std::move(s1));
//
//    return 0;
//}

//int main()
//{
//    list<my_string::string> lt;
//    my_string::string s1("1111");
//
//    // 这里调用的是拷贝构造
//    lt.push_back(s1);
//
//    // 下面调用都是移动构造
//    lt.push_back("2222");
//    lt.push_back(std::move(s1));
//
//    return 0;
//}

//void Fun(int& x) { cout << "左值引用" << endl; }
//void Fun(const int& x) { cout << "const 左值引用" << endl; }
//void Fun(int&& x) { cout << "右值引用" << endl; }
//void Fun(const int&& x) { cout << "const 右值引用" << endl; }
//
//template<typename T>
//void PerfectForward(T&& t)
//{
//    Fun(std::forward<T>(t));
//}
//
//int main()
//{
//    PerfectForward(10);
//
//    int a;
//    PerfectForward(a); 
//    PerfectForward(std::move(a));
//
//    const int b = 8;
//    PerfectForward(b);
//    PerfectForward(std::move(b));
//
//    return 0;
//}

//template<class T>
//struct ListNode
//{
//    ListNode* _next = nullptr;
//    ListNode* _prev = nullptr;
//    T _data;
//};
//
//template<class T>
//class List
//{
//    typedef ListNode<T> Node;
//public:
//    List()
//    {
//        _head = new Node;
//        _head->_next = _head;
//        _head->_prev = _head;
//    }
//
//    void PushBack(T&& x)
//    {
//        //Insert(_head, x);
//        Insert(_head, std::forward<T>(x));
//    }
//
//    void PushFront(T&& x)
//    {
//        //Insert(_head->_next, x);
//        Insert(_head->_next, std::forward<T>(x));
//    }
//
//    void Insert(Node* pos, T&& x)
//    {
//        Node* prev = pos->_prev;
//        Node* newnode = new Node;
//        newnode->_data = std::forward<T>(x); // 关键位置
//        // prev newnode pos
//        prev->_next = newnode;
//        newnode->_prev = prev;
//        newnode->_next = pos;
//        pos->_prev = newnode;
//    }
//
//    void Insert(Node* pos, const T& x)
//    {
//        Node* prev = pos->_prev;
//        Node* newnode = new Node;
//        newnode->_data = x; // 关键位置
//        // prev newnode pos
//        prev->_next = newnode;
//        newnode->_prev = prev;
//        newnode->_next = pos;
//        pos->_prev = newnode;
//    }
//
//private:
//    Node* _head;
//};

//class Person
//{
//public:
//    Person(const char* name = "", int age = 0)
//        :_name(name)
//        , _age(age)
//    {}
//
//    //Person(const Person& p)
//    //    :_name(p._name)
//    //    ,_age(p._age)
//    //    {}
//
//    //Person& operator=(const Person& p)
//    //{
//    //if(this != &p)
//    //{
//    //_name = p._name;
//    //_age = p._age;
//    //}
//    //return *this;
//    //}
//
//    //~Person()
//    //{}
//private:
//    my_string::string _name;
//    int _age;
//};
//
//int main()
//{
//    Person s1;
//    Person s2 = s1;
//    Person s3 = std::move(s1);
//    Person s4;
//    s4 = std::move(s2);
//
//    return 0;
//}

//class Person
//{
//public:
//    Person(const char* name = "", int age = 0)
//        :_name(name)
//        , _age(age)
//    {}
//
//    Person(const Person& p)
//        :_name(p._name)
//        , _age(p._age)
//    {}
//
//    Person(Person&& p) = default;
//
//private:
//    my_string::string _name;
//    int _age;
//};
//
//int main()
//{
//    Person s1;
//    Person s2 = s1;
//    Person s3 = std::move(s1);
//
//    return 0;
//}

//class Person
//{
//public:
//    Person(const char* name = "", int age = 0)
//        :_name(name)
//        , _age(age)
//    {}
//
//    Person(const Person& p) = delete;
//
//private:
//    my_string::string _name;
//    int _age;
//};
//
//int main()
//{
//    Person s1;
//    Person s2 = s1;
//    Person s3 = std::move(s1);
//    return 0;
//}

//// Args是一个模板参数包，args是一个函数形参参数包
//// 声明一个参数包Args...args，这个参数包中可以包含0到任意个模板参数。
//template <class ...Args>
//void ShowList(Args... args)
//{}

//// 递归终止函数
//template <class T>
//void ShowList(const T& t)
//{
//    cout << t << endl;
//}
//
//// 展开函数
//template <class T, class ...Args>
//void ShowList(T value, Args... args)
//{
//    cout << value << " ";
//    ShowList(args...);
//}
//
//int main()
//{
//    ShowList(1);
//    ShowList(1, 'A');
//    ShowList(1, 'A', std::string("sort"));
//
//    return 0;
//}

//template <class T>
//void PrintArg(T t)
//{
//    cout << t << " ";
//}
//
////展开函数
//template <class ...Args>
//void ShowList(Args... args)
//{
//    int arr[] = { (PrintArg(args), 0)... };
//    cout << endl;
//}
//
//int main()
//{
//    ShowList(1);
//    ShowList(1, 'A');
//    ShowList(1, 'A', std::string("sort"));
//    return 0;
//}

//template <class... Args>
//void emplace_back(Args&&... args);

//int main()
//{
//    std::list< std::pair<int, char> > mylist;
//    // emplace_back支持可变参数，拿到构建pair对象的参数后自己去创建对象
//    // 那么在这里我们可以看到除了用法上，和push_back没什么太大的区别
//    mylist.emplace_back(10, 'a');
//    mylist.emplace_back(20, 'b');
//    mylist.emplace_back(make_pair(30, 'c'));
//    mylist.push_back(make_pair(40, 'd'));
//    mylist.push_back({ 50, 'e' });
//    for (auto e : mylist)
//        cout << e.first << ":" << e.second << endl;
//    return 0;
//}

//int main()
//{
//    // 下面我们试一下带有拷贝构造和移动构造的my_string::string，再试试呢
//    // 我们会发现其实差别也不到，emplace_back是直接构造了，push_back
//    // 是先构造，再移动构造，其实也还好。
//    std::list< std::pair<int, my_string::string> > mylist;
//    mylist.emplace_back(10, "sort");
//    mylist.emplace_back(make_pair(20, "sort"));
//    mylist.push_back(make_pair(30, "sort"));
//    mylist.push_back({ 40, "sort" });
//
//    return 0;
//}

//#include <algorithm>
//#include <functional>
//int main()
//{
//    int array[] = { 4,1,8,5,3,7,0,9,2,6 };
//
//    // 默认按照小于比较，排出来结果是升序
//    std::sort(array, array + sizeof(array) / sizeof(array[0]));
//
//    // 如果需要降序，需要改变元素的比较规则
//    std::sort(array, array + sizeof(array) / sizeof(array[0]), greater<int>());
//
//    return 0;
//}

struct Goods
{
    Goods(const char* str, double price, int evaluate)
        :_name(str)
        , _price(price)
        , _evaluate(evaluate)
    {}

    string _name; // 名字
    double _price; // 价格
    int _evaluate; // 评价
};
//
//struct ComparePriceLess
//{
//    bool operator()(const Goods& gl, const Goods& gr)
//    {
//        return gl._price < gr._price;
//    }
//};
//
//struct ComparePriceGreater
//{
//    bool operator()(const Goods& gl, const Goods& gr)
//    {
//        return gl._price > gr._price;
//    }
//};
//
//int main()
//{
//    vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
//   3 }, { "菠萝", 1.5, 4 } };
//
//    sort(v.begin(), v.end(), ComparePriceLess());
//    sort(v.begin(), v.end(), ComparePriceGreater());
//
//    return 0;
//}

//int main()
//{
//    vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
//   3 }, { "菠萝", 1.5, 4 } };
//
//    sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
//        return g1._price < g2._price; });
//    sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
//        return g1._price > g2._price; });
//
//    sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
//        return g1._evaluate < g2._evaluate; });
//    sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
//        return g1._evaluate > g2._evaluate; });
//
//    return 0;
//}

//int main()
//{
//	int a = 0, b = 2;
//	double rate = 2.555;
//	auto add1 = [](int x, int y)->int {return x + y; };
//	auto add2 = [](int x, int y) {return x + y; };
//
//	auto add3 = [rate](int x, int y) {return (x + y)* rate; };
//
//	cout << add1(a, b) << endl;
//	cout << add2(a, b) << endl;
//	cout << add3(a, b) << endl;
//
//
//	auto swap1 = [add1](int& x, int& y) {
//		int tmp = x;
//		x = y;
//		y = tmp;
//
//		cout << add1(x, y) << endl;
//	};
//	swap1(a, b);
//
//	return 0;
//}

//int main()
//{
//	int x = 0, y = 2;
//	auto swap1 = [x, y]() mutable {
//	// mutable让捕捉的x和y可以改变了，
//	// 但是他们依旧是外面x和y的拷贝
//		int tmp = x;
//		x = y;
//		y = tmp;
//	};
//	swap1();
//
//	// 引用的方式捕捉
//	auto swap2 = [&x, &y](){
//		int tmp = x;
//		x = y;
//		y = tmp;
//	};
//	swap2();
//
//	int a = 0;
//	int b = 1;
//	int c = 2;
//	int d = 3;
//	const int e = 1;
//	cout << &e << endl;
//
//	// 引用的方式捕捉所有对象，除了a
//	// a用传值的方式捕捉
//	auto func = [&, a] {
//		//a++;
//		b++;
//		c++;
//		d++;
//		cout << &e << endl;
//	};
//
//	return 0;
//}

//int main()
//{
//	auto f1 = [](int x, int y) {return x + y; };
//	auto f2 = [](int x, int y) {return x + y; };
//
//	//f1 = f2;
//	cout << typeid(f1).name() << endl;
//	cout << typeid(f2).name() << endl;
//
//	f1(1, 2);
//
//
//	return 0;
//}

//class Rate
//{
//public:
//    Rate(double rate) : _rate(rate)
//    {}
//
//    double operator()(double money, int year)
//    {
//        return money * _rate * year;
//    }
//
//private:
//    double _rate;
//};
//
//int main()
//{
//	// 函数对象
//	double rate = 0.49;
//	Rate r1(rate);
//	r1(10000, 2);
//
//	// lambda
//	auto r2 = [=](double monty, int year)->double {return monty * rate * year; };
//	r2(10000, 2);
//
//	return 0;
//}

#include <functional>

// ret = func(x);
// 上面func可能是什么呢？那么func可能是函数名？函数指针？函数对象(仿函数对象)？
// 也有可能是lambda表达式对象？所以这些都是可调用的类型，
// 如此丰富的类型，可能会导致模板的效率低下！为什么呢？我们继续往下看
template<class F, class T>
T useF(F f, T x)
{
    static int count = 0;
    cout << "count:" << ++count << endl;
    cout << "count:" << &count << endl;

    return f(x);
}

double f(double i)
{
    return i / 2;
}

struct Functor
{
    double operator()(double d)
    {
        return d / 3;
    }
};
//
//int main()
//{
//
//	// 函数指针
//	cout << useF(f, 11.11) << endl;
//
//	// 函数对象
//	cout << useF(Functor(), 11.11) << endl;
//
//	// lambda表达式
//	cout << useF([](double d)->double { return d / 4; }, 11.11) << endl;
//
//	// 可调用对象存储到容器中
//	//vector<>
//
//    // 包装器 -- 可调用对象的类型问题
//    function<double(double)> f1 = f;
//    function<double(double)> f2 = [](double d)->double { return d / 4; };
//    function<double(double)> f3 = Functor();
//
//    //vector<function<double(double)>> v = { f1, f2, f3 };
//    vector<function<double(double)>> v = { f, [](double d)->double { return d / 4; }, Functor() };
//
//    double n = 3.3;
//    for (auto f : v)
//    {
//	    cout << f(n++) << endl;
//    }
//
//	return 0;
//}

//int main()
//{
//	// 函数名
//	std::function<double(double)> func1 = f;
//	cout << useF(func1, 11.11) << endl;
//
//	// 函数对象
//	std::function<double(double)> func2 = Functor();
//	cout << useF(func2, 11.11) << endl;
//
//	// lambda表达式
//	std::function<double(double)> func3 = [](double d)->double { return d / 4; };
//	cout << useF(func3, 11.11) << endl;
//
//	return 0;
//}

int Sub(int a, int b)
{
    return a - b;
}

double Plus(int a, int b, double rate)
{
    return (a + b) * rate;
}

double PPlus(int a, double rate, int b)
{
    return  rate * (a + b);
}

class Sub
{
public:
	int sub(int a, int b)
	{
		return a - b;
	}
};

class SubType
{
public:
    static int sub(int a, int b)
    {
        return a - b;
    }

    int ssub(int a, int b, int rate)
    {
        return (a - b) * rate;
    }
};

int main()
{


	/*function<int(int, int)> rSub = bind(Sub, placeholders::_1, placeholders::_2);
	cout << rSub(10, 5) << endl;*/

    // int Sub(int a, int b)
	function<int(int, int)> rSub = bind(Sub, placeholders::_2, placeholders::_1);
	cout << rSub(10, 5) << endl;

    // double Plus(int a, int b, double rate)
	function<double(int, int)> Plus1 = bind(Plus, placeholders::_1, placeholders::_2, 4.0);
	function<double(int, int)> Plus2 = bind(Plus, placeholders::_1, placeholders::_2, 4.2);
	function<double(int, int)> Plus3 = bind(Plus, placeholders::_1, placeholders::_2, 4.4);

	cout << Plus1(5, 3) << endl;
	cout << Plus2(5, 3) << endl;
	cout << Plus3(5, 3) << endl;


	// double PPlus(int a, double rate, int b)
	function<double(int, int)> PPlus1 = bind(PPlus, placeholders::_1, 4.0, placeholders::_2);
	function<double(int, int)> PPlus2 = bind(PPlus, placeholders::_1, 4.2, placeholders::_2);
	cout << PPlus1(5, 3) << endl;
	cout << PPlus2(5, 3) << endl;

    // static int sub(int a, int b)
	function<double(int, int)> Sub1 = bind(&SubType::sub, placeholders::_1, placeholders::_2);

    // int ssub(int a, int b, int rate)
	SubType st;
	function<double(int, int)> Sub2 = bind(&SubType::ssub, &st, placeholders::_1, placeholders::_2, 3);
	cout << Sub1(1, 2) << endl;
	cout << Sub2(1, 2) << endl;

	function<double(int, int)> Sub3 = bind(&SubType::ssub, SubType(), placeholders::_1, placeholders::_2, 3);
	cout << Sub3(1, 2) << endl;

	cout << typeid(Sub3).name() << endl;

	return 0;
}

//class Solution {
//public:
//    int evalRPN(vector<string>& tokens) {
//        stack<int> st;
//        for (auto& str : tokens)
//        {
//            if (str == "+" || str == "-" || str == "*" || str == "/")
//            {
//                int right = st.top();
//                st.pop();
//                int left = st.top();
//                st.pop();
//                switch (str[0])
//                {
//                case '+':
//                    st.push(left + right);
//                    break;
//                case '-':
//                    st.push(left - right);
//                    break;
//                case '*':
//                    st.push(left * right);
//                    break;
//                case '/':
//                    st.push(left / right);
//                    break;
//                }
//            }
//            else
//            {
//                st.push(stoi(str));
//            }
//        }
//        return st.top();
//    }
//};

//class Solution {
//public:
//    int evalRPN(vector<string>& tokens) {
//        stack<int> st;
//        map<string, function<int(int, int)>> opFuncMap =
//        {
//        { "+", [](int i, int j) {return i + j; } },
//        { "-", [](int i, int j) {return i - j; } },
//        { "*", [](int i, int j) {return i * j; } },
//        { "/", [](int i, int j) {return i / j; } }
//        };
//        for (auto& str : tokens)
//        {
//            if (opFuncMap.find(str) != opFuncMap.end())
//            {
//                int right = st.top();
//                st.pop();
//                int left = st.top();
//                st.pop();
//                st.push(opFuncMap[str](left, right));
//            }
//            else
//            {
//                st.push(stoi(str));
//            }
//        }
//        return st.top();
//    }
//};

//template <class Fn, class... Args>
///* unspecified */ bind (Fn&& fn, Args&&... args);
//// with return type (2) 
//template <class Ret, class Fn, class... Args>
///* unspecified */ bind (Fn&& fn, Args&&... args);